# coding: utf-8

# -------------------------------------------------------------------------------
# Name:         http_testsuite_runner.py
# Description:
# Author:       XiangjunZhao
# EMAIL:        2419352654@qq.com
# Date:         2019/11/18 17:32
# -------------------------------------------------------------------------------
import logging
from django.utils import timezone

from apps.HttpAutoTestService.core.ext_method_runner import ExtMethodRunner
from apps.HttpAutoTestService.core.http_testcase_runner import HttpTestcaseRunner
from apps.HttpAutoTestService.core.loader import load_ext_method_online
from apps.HttpAutoTestService.models import TestsuiteResult

logger = logging.getLogger(__name__)


class HttpTestsuiteRunner(object):

    def __init__(self, http_session=None, http_session_context=None, environment=None, project=None, testsuite=None,
                 ext_method_online_module=None, ext_methods_online=None):
        """
        实例化场景运行器
        Args:
            http_session:
            http_session_context:
            environment: 运行环境
            project: 项目
            testsuite: 场景
            ext_method_online_module：ext_method_online.py模块
            ext_methods_online：ext_method_online.py模块中的方法
        """
        self.http_session = http_session
        self.http_session_context = http_session_context
        self.environment = environment
        self.project = project
        self.testsuite = testsuite
        self.ext_method_online_module = ext_method_online_module
        self.ext_methods_online = ext_methods_online
        if ext_method_online_module is None:
            self.ext_method_online_module, self.ext_methods_online = load_ext_method_online()

    def run(self, executor=None, is_periodictask=True):
        logger.info('*************** 执行测试场景:【{name}】***************'.format(name=self.testsuite.name))
        testsuite2testcase_list = self.testsuite.testsuite2testcase.all()
        testsuite_result_mapping = {
            "execute_time": timezone.now(),
            "elapsed_ms": 0,
            "passed_num": 0,
            "failed_num": 0,
            "total_num": 0,
            "status": "PASS",
            "project_id": self.testsuite.project.id,
            "project_name": self.testsuite.project.name,
            "testsuite_id": self.testsuite.id,
            "testsuite_name": self.testsuite.name,
        }

        if not is_periodictask:
            testsuite_result_mapping.update({
                'executor_id': executor.id,
                'executor_real_name': executor.real_name,
                'is_periodictask': is_periodictask
            })

        # 初始化扩展方法执行器
        ext_method_runner = ExtMethodRunner(ext_method_online_module=self.ext_method_online_module,
                                            ext_methods_online=self.ext_methods_online)
        testcase_result_list = []
        ext_method_result_list = []
        for testsuite2testcase in testsuite2testcase_list:
            # 执行 / 跳过
            is_execute = testsuite2testcase.is_execute
            # 循环执行次数
            loop_count = testsuite2testcase.loop_count
            if is_execute:
                if testsuite2testcase.type == 'HTTP_API':
                    # 1、获取场景用例所属接口
                    api = testsuite2testcase.api
                    # 2、获取接口运行环境
                    environment = api.environment
                    if environment:
                        # 3、获取运行环境全局参数
                        environment_variables = environment.global_variables
                        # 4、将运行环境全局参数更新到http_session_context中
                        self.http_session_context.update_session_variables(environment_variables)
                    else:
                        environment = self.environment
                    # 执行http接口用例
                    http_testcase_runner = HttpTestcaseRunner(http_session=self.http_session,
                                                              http_session_context=self.http_session_context,
                                                              environment=environment,
                                                              project=self.project,
                                                              api=api,
                                                              ext_method_online_module=self.ext_method_online_module,
                                                              ext_methods_online=self.ext_methods_online)

                    # 运行测试场景时，测试用例的数据来源于从testcase中冗余到testsuite2testcase中的数据
                    testcase_name = testsuite2testcase.testcase_name
                    url = testsuite2testcase.url
                    headers = testsuite2testcase.headers
                    request_params = testsuite2testcase.request_params
                    request_data_type = testsuite2testcase.request_data_type
                    request_data = testsuite2testcase.request_data
                    expect_result = testsuite2testcase.expect_result
                    temp_testcase_result_list = http_testcase_runner.run(testcase_name=testcase_name,
                                                                         url=url,
                                                                         headers=headers,
                                                                         request_params=request_params,
                                                                         request_data_type=request_data_type,
                                                                         request_data=request_data,
                                                                         expect_result=expect_result,
                                                                         executor=executor,
                                                                         is_periodictask=is_periodictask,
                                                                         loop_count=loop_count)
                    testsuite_result_mapping["total_num"] += len(temp_testcase_result_list)
                    for temp_testcase_result in temp_testcase_result_list:
                        temp_testcase_result.testsuite_name = self.testsuite.name
                        testcase_result_list.append(temp_testcase_result)
                        testsuite_result_mapping["elapsed_ms"] += (
                            temp_testcase_result.elapsed_ms if temp_testcase_result else 0)
                        if temp_testcase_result is None or temp_testcase_result.status == "FAIL":
                            testsuite_result_mapping["failed_num"] += 1
                            testsuite_result_mapping["status"] = "FAIL"
                        elif temp_testcase_result and temp_testcase_result.status == "PASS":
                            testsuite_result_mapping["passed_num"] += 1
                elif testsuite2testcase.type == 'EXT_METHOD':
                    # 执行扩展方法
                    ext_method_name = testsuite2testcase.ext_method_name
                    ext_method = testsuite2testcase.ext_method
                    expect_result = testsuite2testcase.expect_result
                    temp_ext_method_result_list = ext_method_runner.run(http_session=self.http_session,
                                                                        http_session_context=self.http_session_context,
                                                                        ext_method_name=ext_method_name,
                                                                        ext_method=ext_method,
                                                                        expect_result=expect_result,
                                                                        executor=executor,
                                                                        is_periodictask=is_periodictask,
                                                                        loop_count=loop_count)

                    testsuite_result_mapping["total_num"] += len(temp_ext_method_result_list)
                    for temp_ext_method_result in temp_ext_method_result_list:
                        temp_ext_method_result.testsuite_name = self.testsuite.name
                        ext_method_result_list.append(temp_ext_method_result)
                        testsuite_result_mapping["elapsed_ms"] += (
                            temp_ext_method_result.elapsed_ms if temp_ext_method_result else 0)
                        if temp_ext_method_result is None or temp_ext_method_result.status == "FAIL":
                            testsuite_result_mapping["failed_num"] += 1
                            testsuite_result_mapping["status"] = "FAIL"
                        elif temp_ext_method_result and temp_ext_method_result.status in ("PASS", None):
                            # None：表示扩展方法不进行校验，比如sleep方法
                            testsuite_result_mapping["passed_num"] += 1
                # 更新场景结果状态
                if testsuite_result_mapping["passed_num"] == testsuite_result_mapping["total_num"]:
                    testsuite_result_mapping["status"] = "PASS"
                elif testsuite_result_mapping["failed_num"] > 0 and testsuite_result_mapping["passed_num"] > 0:
                    testsuite_result_mapping["status"] = "PARTIAL_PASS"
                elif testsuite_result_mapping["failed_num"] == testsuite_result_mapping["total_num"]:
                    testsuite_result_mapping["status"] = "FAIL"
        testsuite_result = TestsuiteResult(**testsuite_result_mapping)
        return testsuite_result, testcase_result_list, ext_method_result_list
